package com.example.lambda;

import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: fxbin
 * @Date: 2018/5/28 11:21
 * @Description:   转换stream
 */
public class TransformStreamTest {

    public static void main(String[] args) {

//        testAll();

//        testPeek();
//        collectHTest();
        collectETest();
    }


    /**
     * distinct: 对于Stream中包含的元素进行去重操作（去重逻辑依赖元素的equals方法），新生成的Stream中没有重复的元素;
     * filter: 对于Stream中包含的元素使用给定的过滤函数进行过滤操作，新生成的Stream只包含符合条件的元素;
     *  map: 对于Stream中包含的元素使用给定的转换函数进行转换操作，新生成的Stream只包含转换生成的元素。
     *       这个方法有三个对于原始类型的变种方法，分别是：mapToInt，mapToLong和mapToDouble。
     *       这三个方法也比较好理解，比如mapToInt就是把原始Stream转换成一个新的Stream，这个新生成的Stream中的元素都是int类型。
     *       之所以会有这样三个变种方法，可以免除自动装箱/拆箱的额外消耗;
     *  flatMap：和map类似，不同的是其每个元素转换得到的是Stream对象，会把子Stream中的元素压缩到父集合中;
     *  peek: 生成一个包含原Stream的所有元素的新Stream，同时会提供一个消费函数（Consumer实例），
     *         新Stream每个元素被消费的时候都会执行给定的消费函数
     *   limit: 对一个Stream进行截断操作，获取其前N个元素，如果原Stream中包含的元素个数小于N，那就获取其所有的元素;
     *   skip: 返回一个丢弃原Stream的前N个元素后剩下元素组成的新Stream，如果原Stream中包含的元素个数小于N，那么返回空Stream;
     */
    public static void testAll(){
        List<Integer> nums = Lists.newArrayList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
        System.out.println("sum is:" + nums.stream().filter(num -> num != null)
                .distinct().mapToInt(num -> num * 2)
                .peek(System.out::println)
                .skip(2)
                .limit(4)
                .sum()

        );
    }

    public static void testPeek(){
        List<Integer> nums = Lists.newArrayList(1, 2, 3, 4, 5, 6);

        nums.stream().mapToInt(num -> num).peek(System.out::println);
    }

    /**
     *  复杂版：
     *
     *  1. 先过滤掉全部的null,
     *  2.然后把剩下的元素收集到一个新的list 中
     *
     *
     *  第一个函数生成一个新的ArrayList实例；
     *
     *  第二个函数接受两个参数，第一个是前面生成的ArrayList对象，第二个是stream中包含的元素，函数体就是把stream中的元素加入ArrayList对象中。第二个函数被反复调用直到原stream的元素被消费完毕；
     *  第三个函数也是接受两个参数，这两个都是ArrayList类型的，函数体就是把第二个ArrayList全部加入到第一个中；
     *
     */
    public static void collectHTest(){
        List<Integer> nums = Lists.newArrayList(1,1,null,2,3,4,null,5,6,7,8,9,10);
        List<Integer> numList = nums.stream().filter(num -> num != null)
                .collect(() -> new ArrayList<Integer>(),
                        (list, item) -> list.add(item),
                        (list1, list2) -> list1.addAll(list2));
        System.out.println(numList);
    }

    /**
     *  简易版。。。实现
     */
    public static void collectETest(){
        List<Integer> nums = Lists.newArrayList(1,1,null,2,3,4,null,5,6,7,8,9,10);
        List<Integer> numList = nums.stream().filter(num -> num != null).collect(Collectors.toList());
        System.out.println(numList);
    }




}    